<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
  
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  
  <link href="../css/style.css" rel="stylesheet" type="text/css">

</head>
<body>
<h1>4.9. Режимы адресации</h1>
<p class="article">
Режимы адресации — это различные способы указания местоположения операндов. До этой части в учебном курсе использовались только простые режимы адресации: операнды чаще всего находились в регистрах или в переменных в памяти. Но в процессоре Intel 8086 существуют также более сложные режимы, которые позволяют организовать работу с массивами, структурами, локальными переменными и указателями. В этой части я расскажу о всех возможных режимах адресации и приведу примеры их использования.
</p>
<h2>1. Неявная адресация</h2>
<p class="article">
Местоположение операнда фиксировано и определяется кодом операции. Примеры:
<pre class="code">
    cbw
    mul al
</pre>
Команда CBW всегда работает с регистрами AX и AL, а у команды MUL фиксировано положение первого множителя и результата. Такой режим адресации делает машинную команду короткой, так как в ней отсутствует указание одного или нескольких операндов.
</p>
<h2>2. Непосредственная адресация</h2>
<p class="article">
При непосредственной адресации значение операнда является частью машинной команды. Понятно, что в этом случае операнд представляет собой константу. Примеры:
<pre class="code">
    mov al,5
    add bx,1234h
    mov dx,a
</pre>
</p>
<div class="noteimportant">
Обратите внимание, что в третьей строке в DX помещается адрес метки или переменной a, а вовсе не значение по этому адресу. Это особенность синтаксиса FASM. По сути адрес метки тоже является числовой константой.
</div>
<h2>3. Абсолютная прямая адресация</h2>
<p class="article">
В машинной команде содержится адрес операнда, находящегося в памяти. Пример:
<pre class="code">
    mov dx,[a]
</pre>
Вот тут уже в DX помещается значение из памяти по адресу a. Сравните с предыдущим пунктом. Квадратные скобки обозначают обращение по адресу, указанному внутри этих скобок.
</p>
<h2>4. Относительная прямая адресация</h2>
<p class="article">
Этот режим используется в командах передачи управления. В машинной команде содержится смещение, которое прибавляется к значению указателя команд IP. То есть указывается не сам адрес перехода, а на сколько байтов вперёд или назад надо перейти. Пример:
<pre class="code">
metka:
    ...
    loop metka
</pre>
У такого режима адресации два преимущества. Во-первых, машинная команда становится короче, так она содержит не полный адрес, а только смещение. Во-вторых, такой код не зависит от адреса, по которому он размещается в памяти.
</p>
<h2>5. Регистровая адресация</h2>
<p class="article">
Операнд находится в регистре. Пример:
<pre class="code">
    add ax,bx
</pre>
</p>
<h2>6. Косвенная регистровая (базовая) адресация</h2>
<p class="article">
Адрес операнда находится в одном из регистров BX, SI или DI. Примеры:
<pre class="code">
    add ax,[bx]
    mov dl,[si]
</pre>
Размер операнда в памяти здесь определяется размером первого операнда. Так как AX — 16-разрядный регистр, то из памяти берётся слово по адресу в BX. Так как DL — 8-разрядный регистр, то из памяти берётся байт по адресу в SI. Это правило верно и для других режимов адресации.
</p>
<h2>7. Косвенная регистровая (базовая) адресация со смещением</h2>
<p class="article">
Адрес операнда вычисляется как сумма содержимого регистра BX, BP, SI или DI и 8- или 16-разрядного смещения. Примеры:
<pre class="code">
    add ax,[bx+2]
    mov dx,[array1+si]
</pre>
В качестве смещения можно указать число или адрес метки. О размере смещения не беспокойтесь — компилятор сам его определяет и использует нужный формат машинной команды.
</p>
<h2>8. Косвенная базовая индексная адресация</h2>
<p class="article">
Адрес операнда вычисляется как сумма содержимого одного из базовых регистров BX или BP и одного из индексных регистров SI или DI. Примеры:
<pre class="code">
    mov ax,[bp+si]
    add ax,[bx+di]
</pre>
Например, в одном из регистров может находиться адрес начала массива в памяти, а в другом — смещение какого-то элемента относительно начала.
</p>
<h2>9. Косвенная базовая индексная адресация со смещением</h2>
<p class="article">
Адрес операнда вычисляется как сумма содержимого одного из базовых регистров BX или BP, одного из индексных регистров SI или DI и 8- или 16-разрядного смещения. Примеры:
<pre class="code">
    mov al,[bp+di+5]
    mov bl,[array2+bx+si]
</pre>
</p>
<h2>Пример программы</h2>
<p class="article">
Допустим, имеется массив 32-битных целых чисел со знаком. Количество элементов массива хранится в 16-битной переменной без знака. Требуется вычислить среднее арифметическое элементов массива и сохранить его в 32-битной переменной со знаком. Я намеренно использовал разные режимы адресации, хотя тоже самое можно написать проще.
<pre class="code">
use16                   ;Генерировать 16-битный код
org 100h                ;Программа начинается с адреса 100h
 
      sub ax,ax         ;AX = 0
      cwd               ;DX = 0
      mov si,ax         ;SI = 0 - смещение элемента от начала массива
      mov bx,array      ;Помещаем в BX адрес начала массива
      mov di,n          ;Помещаем в DI адрес n
      mov cx,[di]       ;CX = n
lp1:
      add ax,[bx+si]    ;Прибавление младшего слова
      adc dx,[bx+si+2]  ;Прибавление старшего слова
      add si,4          ;Увеличиваем смещение в SI на 4
      loop lp1          ;Команда цикла
 
      idiv word[di]     ;Делим сумму на количество элемнтов
      cwd               ;DX:AX = AX
      mov word[m],ax    ;\ Сохраняем
      mov word[m+2],dx  ;/ результат
 
      mov ax,4C00h      ;\
      int 21h           ;/ Завершение программы
;-------------------------------------------------------
n     dw 10
array dd 10500,-7500,-15000,10000,-8000
      dd 6500,11500,-5000,10500,-20000
m     dd ?
</pre>
</p>
</body>
</html>
